﻿''' <summary>
''' 所属している全グループ画面のフォームです。
''' </summary>
''' <remarks></remarks>
Public Class InRoleGroupList
  Inherits Page

#Region " プライベートフィールド "
  Private member As DomainObject  'メンバー
  Private allGroups As Dictionary(Of String, DomainGroup)   '全グループ(Key:distinguishedName)
  Private addedDistinguishedNames As List(Of String)  'ノードに追加したグループの識別名
#End Region

#Region " イベントハンドラ "
  Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    Dim name = Request.QueryString("name")  '名前
    If String.IsNullOrEmpty(name) Then
      Return
    End If

    Dim category As CategoryType  'Directory オブジェクトの種類
    If [Enum].TryParse(Of CategoryType)(Request.QueryString("category"), category) = False Then
      Return
    End If
    If Me.IsPostBack Then
      Return
    End If

    Select Case category  'Directory オブジェクトの種類
      Case CategoryType.User
        member = DomainUser.FindByName(name)  'ユーザーを検索
      Case CategoryType.Group
        member = DomainGroup.FindByName(name) 'グループを検索
      Case CategoryType.Computer
        member = Computer.FindByName(name)    'コンピューターを検索
    End Select
    If member Is Nothing Then
      Return
    End If

    allGroups = DirectoryAccess.GetGroups(Of DomainGroup)().ToDictionary(
      Function(group) group.Entry.Properties.Item("distinguishedName").Value.ToString(), Function(group) group)
    addedDistinguishedNames = New List(Of String)()

    Me.AddChildNode()   '子ノードを追加
    Me.GroupListBox.DataSource = CreateGroupTable()   'データソース用のテーブルを作成
    Me.GroupListBox.DataTextField = "Text"
    Me.GroupListBox.DataValueField = "Value"
    If addedDistinguishedNames.Count > 1 Then
      Me.GroupListBox.Style.Add(HtmlTextWriterStyle.BorderStyle, "None")
    Else
      Me.ViewRadioButtonList.Enabled = False
    End If
    Me.GroupListBox.DataBind()

    member.Dispose()
    DirectoryAccess.DisposeItems(allGroups.Values)
  End Sub

  Protected Sub ViewRadioButtonList_SelectedIndexChanged(
    sender As Object, e As EventArgs) Handles ViewRadioButtonList.SelectedIndexChanged

    Me.GroupTreeView.Visible = (Me.ViewRadioButtonList.SelectedIndex = 0)
    Me.GroupListBox.Visible = Not Me.GroupTreeView.Visible
  End Sub
#End Region

#Region " プライベートメソッド "
  ''' <summary>
  ''' 子ノードを追加します。
  ''' </summary>
  ''' <remarks></remarks>
  Private Sub AddChildNode()
    Dim node As New TreeNode(member.ToString(), member.Name)
    Me.GroupTreeView.Nodes.Add(node)
    If (member.Category = CategoryType.User) OrElse (member.Category = CategoryType.Computer) Then
      'プライマリーグループを追加
      Dim primaryGroupId = If(member.Category = CategoryType.User,
        DirectCast(member, DomainUser).PrimaryGroupId, DirectCast(member, Computer).PrimaryGroupId)
      Dim group = allGroups.Values.Cast(Of DomainGroup)().Single(Function(grp) grp.Token = primaryGroupId)
      Me.AddChildNode(node, group)  '子ノードを追加
    End If
    '所属するグループを追加
    For Each memberOf As String In member.Entry.Properties.Item("memberOf")
      Me.AddChildNode(node, allGroups.Item(memberOf))   '子ノードを追加
    Next
  End Sub

  ''' <summary>
  ''' 子ノードを追加します。
  ''' </summary>
  ''' <param name="node">子ノードを追加するノード。</param>
  ''' <param name="group">子ノードになるグループ。</param>
  ''' <remarks></remarks>
  Private Sub AddChildNode(node As TreeNode, group As DomainGroup)
    Dim displayName = String.Format("{0}（{1}）", group.Name, group.Scope)  '表示するテキスト
    Dim distinguishedName = group.Entry.Properties.Item("distinguishedName").Value.ToString()   '識別名
    Dim childNode As New TreeNode(displayName, group.Name)  'ノードを作成

    node.ChildNodes.Add(childNode)
    If addedDistinguishedNames.Contains(distinguishedName) = False Then
      addedDistinguishedNames.Add(distinguishedName)  '識別名を追加
    End If
    'ネストしているグループを追加
    For Each memberOf As String In group.Entry.Properties.Item("memberOf")
      Me.AddChildNode(childNode, allGroups.Item(memberOf))  '子ノードを追加
    Next
  End Sub

  ''' <summary>
  ''' データソース用のテーブルを作成します。
  ''' </summary>
  ''' <returns>データソース用のテーブル。</returns>
  ''' <remarks></remarks>
  Private Function CreateGroupTable() As DataTable
    Dim table As New DataTable()
    table.Columns.Add(New DataColumn("Value", GetType(String)))   '値(distinguishedName)
    table.Columns.Add(New DataColumn("Text", GetType(String)))    '表示するテキスト

    For Each distinguishedName In addedDistinguishedNames   'ノードに追加したグループ数分
      Dim row = table.NewRow()
      Dim group = allGroups.Item(distinguishedName)
      Dim displayName = String.Format("{0}（{1}）", group.Name, group.Scope)

      row.Item(0) = distinguishedName
      row.Item(1) = displayName
      table.Rows.Add(row)
    Next
    Return table
  End Function
#End Region
End Class